/**
 *
 * User: Zhikang.Peng
 * Date: 2018/06/20 10:56
 */
package references

import (
	"gitee.com/thghh/jvmgo/instructions/base"
	"gitee.com/thghh/jvmgo/rtda"
	"gitee.com/thghh/jvmgo/rtda/heap"
)

const (
	AT_BOOLEAN = 4
	AT_CHAR    = 5
	AT_FLOAT   = 6
	AT_DOUBLE  = 7
	AT_BYTE    = 8
	AT_SHORT   = 9
	AT_INT     = 10
	AT_LONG    = 11
)

// 创建一个指定原始类型（如int, float, char…）的数组，并将其引用值压入栈顶
type NEW_ARRAY struct {
	atype uint8
}

func (self *NEW_ARRAY) FetchOperands(reader *base.BytecodeReader) {
	self.atype = reader.ReadUint8()
}

func (self *NEW_ARRAY) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	count := stack.PopInt()
	if count < 0 {
		panic("java.lang.NegativeArraySizeException")
	}
	classLoader := frame.Method().Class().ClassLoader()
	arrayClass := getPrimitiveArrayClass(classLoader, self.atype)
	array := arrayClass.NewArray(uint(count))
	stack.PushReference(array)
}

func getPrimitiveArrayClass(loader *heap.ClassLoader, atype uint8) *heap.Class {
	switch atype {
	case AT_BOOLEAN:
		return loader.LoaderClass("[Z")
	case AT_BYTE:
		return loader.LoaderClass("[B")
	case AT_CHAR:
		return loader.LoaderClass("[C")
	case AT_SHORT:
		return loader.LoaderClass("[S")
	case AT_INT:
		return loader.LoaderClass("[I")
	case AT_LONG:
		return loader.LoaderClass("[J")
	case AT_FLOAT:
		return loader.LoaderClass("[F")
	case AT_DOUBLE:
		return loader.LoaderClass("[D")
	default:
		panic("Invalid atype!")
	}
}
